package com.bblocks.common.anti_reptile.rule;

import com.bblocks.common.anti_reptile.config.bean.RuleComm;
import com.bblocks.common.anti_reptile.constant.RuleResultEnum;
import com.bblocks.common.anti_reptile.module.MatchResult;
import com.bblocks.common.anti_reptile.rateLimiter.RateLimiterPlan;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author Jin
 * @since 2024/3/23 14:40
 */
public interface AntiReptileRule {
    /**
     * 反爬规则具体实现
     * @param request 请求
     * @param response 响应
     * @return 存在则为击中反爬规则
     */
    MatchResult match(HttpServletRequest request, HttpServletResponse response);

    /**
     * 重置已记录规则
     * 2种类型规则：
     * 1、规则固定支持一个锁定类型
     * 2、规则支持动态锁定类型
     * 原则：
     * 1、resetType=空，则不限制解除类型
     * 2、resetType!=null,则只解除指定的类型
     * @param request 请求
     * @param realRequestUri 原始请求uri
     * @param resetTypeLimit  解除类型，为空则都清除，一般情况业务系统 只解除验证码名单(RuleResultEnum.RATELIMIT_CAPTCHA)
     */
    MatchResult reset(HttpServletRequest request, String realRequestUri,RuleResultEnum resetTypeLimit);

    /**
     * 规则优先级（正序）
     * @return 优先级
     */
    int getOrder();


    /**
     * 重置-验证码解除，未清理限流数据
     * @param rule
     * @param rateLimiterPlan
     * @param id
     * @param resetTypeLimit
     * @return 1=成功
     */
    default MatchResult resetDefault(RuleComm rule, RateLimiterPlan rateLimiterPlan, String id,RuleResultEnum resetTypeLimit) {
        boolean mixRule = rule.isMixRule();
        if(!mixRule){//非混合类型的,如果要求的不一致，直接退出
            if(resetTypeLimit != null && !resetTypeLimit.getLockType().equals(rule.getLockType())){//不一致
                return null;
            }
        }

        RuleResultEnum outRuleResult = rateLimiterPlan.outBlack(rule,id,resetTypeLimit);
        if(outRuleResult == null)
            return null;

        if(outRuleResult.getLockType().equals(rule.getLockType())){//和原始配置一直
            return MatchResult
                    .builder()
                    .matchRule(rule)
                    .id(id)
                    .build();
        }else{//和原始配置不一致
            rule = RuleComm.cloneOne(rule);
            rule.setLockType(outRuleResult.getLockType());
            return MatchResult
                    .builder()
                    .matchRule(rule)
                    .id(id)
                    .build();
        }
    }
}
